﻿using DrawableObjects.Actors.Weapons;
using DrawableObjects.Actors.Aircrafts.Controller;
using InterfaceComponents;
using Microsoft.Xna.Framework;
using DrawableObjects.Actors.Projectiles;
using System.Collections.Generic;
using SpecialEffects;
using System;

namespace DrawableObjects.Actors.Aircrafts 
{
    public abstract class Aircraft : Actor
    {
        /// <summary>
        /// Indestructible_Projectiles: Does not take damage from projectiles
        /// Indestructible_Collissions: Does not take damage from collissions with other aircraft
        /// Armoured: Only takes a limited percentage of damage from collissions with other aircrafts
        /// Triggers_Victory: destruction of this aircraft leads to victory
        /// Triggers_Defeat: destruction of this aircraft leads to defeat
        /// Transparent_Aircraft: does not collide with projectiles
        /// Transparent_Projectile: does not collide with projectiles
        /// </summary>
        public enum AircraftAttributes { Indestructible_Projectiles, Indestructible_Collissions, Armoured, Triggers_Victory, Triggers_Defeat, Transparent_Projectile, Transparent_Aircraft };

        public List<AircraftAttributes> aircraftAttributes;

	    public Weaponsystem[] weaponsystems
	    {
		    get;
		    private set;
	    }

	    public HUDWrapper<int> health
	    {
		    get;
		    protected set;
	    }

        public int maxHealth
        {
            get;
            protected set;
        }

	    public Item dropItem
	    {
		    get;
		    set;
	    }

	    public AircraftController controller
	    {
		    get;
		    set;
	    }

	    public int killScore
	    {
		    get;
		    protected set;
	    }

        private BasicExplosion explosion;
        private BasicExplosion smokeExplosion;

        public event GlobalGameClasses.Eventhandler.UpgradeEventHandler WeaponUpgrade;

        public override void Update()
        {
            if (weaponsystems != null)
            {
                foreach (Weaponsystem system in weaponsystems)
                {
                    system.Update();
                }
            }
            base.Update();
        }

        protected Aircraft(Weaponsystem[] weaponsystems, int killScore, Item dropItem, HUDWrapper<int> health, string strModel, Matrix worldMatrix, float scaleFactor, float boundingFactor)
            : base(strModel, worldMatrix, scaleFactor, boundingFactor)
	    {
            this.weaponsystems = weaponsystems;
            this.killScore = killScore;
            this.dropItem = dropItem;
            this.health = health;
            this.maxHealth = health.value;
            this.aircraftAttributes = new List<AircraftAttributes>();
	    }

        public void Fire(Vector2 direction)
	    {
            if (weaponsystems != null)
            {
                for (int i = 0; i < weaponsystems.Length; i++)
                {
                    if (weaponsystems[i].IsReady())
                    {
                        Projectile projectile = weaponsystems[i].Fire(direction, getGamePosition());
                        projectile.owner = this.owner;
                        world.addActor(projectile);
                    }
                }
            }
	    }

        public void addHealthBar(HUDComponent healthbar)
        {
            this.health.AddComponent(healthbar);
        }

        //links a weaponssystem of the given type to the weaponbar
        public void addWeaponBar(HUDComponent weaponBar, Weapon.WeaponType type)
        {
            if (weaponsystems != null)
            {
                int i = 0;
                if (weaponsystems.Length > 0) 
                {
                    while (i + 1 < weaponsystems.Length && weaponsystems[i].weaponCategory != type) { i++; }
                }
                if (weaponsystems[i].weaponCategory == type)
                {
                    weaponsystems[i].level.AddComponent(weaponBar);
                    weaponBar.SetValue(weaponsystems[i].level);
                }
            }
        }

        public void Fire(int weaponID, Vector2 direction)
        {
            if (weaponsystems != null)
            {
                if (weaponsystems.Length > weaponID)
                {
                    if (weaponsystems[weaponID].IsReady())
                    {
                        Projectile projectile = weaponsystems[weaponID].Fire(direction, getGamePosition());
                        projectile.owner = this.owner;
                        projectile.world = this.world;
                        world.addActor(projectile);
                    }
                }

            }
        }

        public void Fire(int weaponID, Vector2 direction, Owner ownerID) {
            if (weaponsystems != null) {
                if (weaponsystems.Length > weaponID) {
                    if (weaponsystems[weaponID].IsReady()) {
                        Projectile projectile = weaponsystems[weaponID].Fire(direction, getGamePosition());
                        projectile.owner = ownerID;
                        projectile.world = this.world;
                        world.addActor(projectile);
                    }
                }

            }
        }

        public void Upgrade(Weapons.Weapon.WeaponType type)
        {
            if (weaponsystems != null)
            {
                foreach (Weaponsystem system in weaponsystems)
                {
                    if (system.weaponCategory == (type))
                    {
                        if (system.Upgrade())
                        {
                            WeaponUpgrade(this, system);
                        }
                    }
                }
            }
        }

        public override void collide(Actor actor2)
        {
            collideWith(actor2);
            if (actor2 is Projectile)
            {
                if (actor2.owner != this.owner && !this.aircraftAttributes.Contains(AircraftAttributes.Indestructible_Projectiles) && !this.aircraftAttributes.Contains(AircraftAttributes.Transparent_Aircraft))
                {
                    this.health.value -= (int)((Projectile)actor2).getDamage();
                    if (this.health.value > maxHealth) {
                        this.health.value = maxHealth;
                    }
                }
            }
            else if (actor2 is Aircraft && actor2.owner != this.owner)
            {
                if (!this.aircraftAttributes.Contains(AircraftAttributes.Indestructible_Collissions) && !this.aircraftAttributes.Contains(AircraftAttributes.Transparent_Aircraft) && !((Aircraft)actor2).aircraftAttributes.Contains(AircraftAttributes.Transparent_Aircraft))
                {
                    if (this.aircraftAttributes.Contains(AircraftAttributes.Armoured))
                    {
                        // Actor is damaged by collission
                        this.health.value -= maxHealth / 4;
                        if (GlobalGameClasses.GlobalGameValues.Values.difficulty == GlobalGameClasses.Difficulty.DIFFICULTY_VERY_HARD) {
                            this.health.value -= maxHealth;
                        }
                    }
                    else
                    {
                        this.health.value = 0;
                    }
                }
            }
            else if (actor2 is WeaponUpgrade)
            {
                if (controller is AIControlledAircraft_Drone)
                {
                    ((AIControlledAircraft_Drone)controller).UpgradeOwnerShip(((WeaponUpgrade)actor2).weaponCategory);
                }
                else
                {
                    Upgrade(((WeaponUpgrade)actor2).weaponCategory);
                }
            }

            //Adds the damage smoke of the player ship
            if (controller is PlayerControlledAircraft)
            {
                if (this.health.value < maxHealth / 6.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel5_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
                else if (this.health.value < maxHealth / 5.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel4_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
                else if (this.health.value < maxHealth / 4.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel3_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
                else if (this.health.value < maxHealth / 3.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel2_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
                else if (this.health.value < maxHealth / 2.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel1_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
            }

            //Adds the damage smoke of the boss
            if (controller is AIControlledAircraft_Boss)
            {
                if (this.health.value < maxHealth / 6.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel5_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
                else if (this.health.value < maxHealth / 5.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel4_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
                else if (this.health.value < maxHealth / 4.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel3_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
                else if (this.health.value < maxHealth / 3.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel2_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
                else if (this.health.value < maxHealth / 2.0f)
                {
                    ((SpecialEffectsAircraft)this).damageSmoke = BasicFireAndSmoke.CreateSmokeLevel1_Player();
                    ((SpecialEffectsAircraft)this).damageSmoke.SetDirection(Vector3.Up);
                    ((SpecialEffectsAircraft)this).hasDamageSmoke = true;
                    world.addSpecialEffect(((SpecialEffectsAircraft)this).damageSmoke);
                }
            }

            if (this.health.value <= 0)
            {
                if (this.dropItem != null)
                {
                    this.dropItem.setPosition(this.getGamePosition());
                    world.addActor(this.dropItem);
                    world.removeActor(this);
                }
                if (controller is PlayerControlledAircraft)
                {
                    // Actor is destroyed
                    smokeExplosion = BasicExplosion.CreateSmokeExpl_Player(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                    explosion = BasicExplosion.CreateExpl_Player(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                    world.addSpecialEffect(smokeExplosion);
                    world.addSpecialEffect(explosion);
                    destroy(actor2);
                }
                else if (controller is AIControlledAircraft_PathGuided)
                    {
                        Random random = new Random();
                        int enemy = random.Next(1, 6);
                        smokeExplosion = BasicExplosion.CreateSmokeExpl_Enemy(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                        switch (enemy)
                        {
                            case 1:
                                explosion = BasicExplosion.CreateExpl_Enemy1(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                                break;

                            case 2:
                                explosion = BasicExplosion.CreateExpl_Enemy2(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                                break;

                            case 3:
                                explosion = BasicExplosion.CreateExpl_Enemy3(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                                break;

                            case 4:
                                explosion = BasicExplosion.CreateExpl_Enemy4(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                                break;

                            case 5:
                                explosion = BasicExplosion.CreateExpl_Enemy5(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                                break;
                        }
                        world.addSpecialEffect(smokeExplosion);
                        world.addSpecialEffect(explosion);
                        destroy(actor2);
                        
                    }
                else if(controller is AIControlledAircraft_Boss)
                    {
                        smokeExplosion = BasicExplosion.CreateSmokeExpl_Boss(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                        explosion = BasicExplosion.CreateExpl_Boss(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                        world.addSpecialEffect(smokeExplosion);
                        world.addSpecialEffect(explosion);
                        destroy(actor2);
                    }
                    else
                        if (controller is AIControlledAircraft_Drone)
                        {
                            smokeExplosion = BasicExplosion.CreateSmokeExpl_Enemy(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                            explosion = BasicExplosion.CreateExpl_Missile(worldMatrix.Translation, new Vector3(moveDirection.X, 0, moveDirection.Y), (float)GlobalGameClasses.GlobalGameValues.Values.gameTime.TotalGameTime.TotalMilliseconds);
                            world.addSpecialEffect(smokeExplosion);
                            world.addSpecialEffect(explosion);
                            destroy(actor2);
                        }
                
            }
        }
    }
}

